/** 将树结构转换为集合
 * @param {T extends { children: any[] } } treeData 树形结构数据
 * @param { U extends T } dataList 生成的集合数据
 * @returns 处理之后的结果
 */
export const treeDataToArray = <
  T extends { children: T[] | null; [key: string]: string | T[] | null },
  U extends { [key: string]: any }
>(
  treeData: T[]
): U[] => {
  let dataList: U[] = [];
  treeData.forEach((item) => {
    let itemData: { [key: string]: any } = {};
    Object.keys(item).forEach((oitem) => {
      if (oitem !== "children") {
        itemData[oitem] = item[oitem];
      }
    });
    dataList.push(itemData as U);
    if (item.children && item.children.length > 0) {
      // 如果当前节点有子节点，递归查找子节点
      dataList = dataList.concat(treeDataToArray(item.children));
    }
  });
  return dataList;
};

/**
 * 将扁平数组转换为树结构
 * @param {any[]} data 扁平数据数组
 * @param {string} [id='id'] 节点唯一标识字段名，默认 'id'
 * @param {string} [parentId='parentId'] 父节点字段名，默认 'parentId'
 * @param {string} [children='children'] 子节点字段名，默认 'children'
 * @returns {any[]} 树结构数组
 *
 * 示例：
 * arrayToTreeData(list, 'id', 'parentId', 'children')
 */
export const arrayToTreeData = (
  data: any[],
  id: string = "id",
  parentId: string = "parentId",
  children: string = "children"
): any[] => {
  const result: any[] = [];
  const map: { [key: string]: any } = {};

  data.forEach((item) => {
    map[item[id]] = { ...item };
  });

  data.forEach((item) => {
    const parent = map[item[parentId]];
    if (parent) {
      if (!parent[children]) parent[children] = [];
      parent[children].push(map[item[id]]);
    } else {
      result.push(map[item[id]]);
    }
  });

  return result;
};

/** 给定一个集合checkList   返回该集合在树形结构中对应的对象
 * @param { T extends { treeList: any[], checkList: any[], field: string }[] } data 待处理的树结构数据
 * @returns {U[]} 处理之后的结果
 */
export const getCheckListByTree = <
  T extends { treeList: any[]; checkList: any[]; field: string },
  U extends { [key: string]: any }
>(
  data: T
): U[] => {
  let result: U[] = [];
  if (data.checkList && data.checkList.length > 0) {
    data.treeList.forEach((item) => {
      if (data.checkList.some((sitem) => sitem === item[data.field])) {
        let itemData: { [key: string]: any } = {};
        Object.keys(item).forEach((oitem) => {
          if (oitem !== "children") {
            itemData[oitem] = item[oitem];
          }
        });
        result.push(itemData as U);
      }
      if (item.children && item.children.length > 0) {
        result = result.concat(
          getCheckListByTree({
            treeList: item.children,
            checkList: data.checkList,
            field: data.field,
          })
        );
      }
    });
  }
  return result;
};

/**
 * 判断指定数据是否存在于树结构中，返回匹配到的节点对象数组（只返回第一个匹配结果）
 * @param data 要查找的值
 * @param treeList 树结构数组
 * @param code 节点唯一标识字段名，默认 'id'
 * @returns 匹配到的节点对象数组，未找到则返回空数组
 *
 * 示例：
 * const tree = [
 *   { id: 1, children: [
 *     { id: 2, children: [
 *       { id: 4 }
 *     ]},
 *     { id: 3 }
 *   ]}
 * ];
 * getDataByTree(4, tree) // 返回: [ { id: 4 } ]
 */
export const getDataByTree = (
  data: string,
  treeList: any[],
  code = "id"
): any => {
  for (const item of treeList) {
    if (item[code] == data) {
      return item;
    }
    if (item.children && item.children.length > 0) {
      const found = getDataByTree(data, item.children, code);
      if (found) return found;
    }
  }
  return null;
};

/**
 * 根据节点id，递归获取该节点及其所有父节点（从子到父，返回路径数组）
 * @param data.treeList 完整的树结构数组
 * @param data.value 当前查找的节点id
 * @param data.field 节点id对应的字段名
 * @returns 包含目标节点及其所有父节点的数组，顺序为[目标节点, 父节点, ... 顶级节点]
 *
 * 示例：
 * const tree = [
 *   { id: 1, children: [
 *     { id: 2, children: [
 *       { id: 3 }
 *     ]}
 *   ]}
 * ];
 * getAllParentArr({ treeList: tree, value: 3, field: 'id' })
 * // 返回: [{id:3}, {id:2}, {id:1}]
 */
export const getAllParentArr = <
  T extends { treeList: any[]; value: string; field: string }
>(
  data: T
) => {
  for (let i in data.treeList) {
    if (data.treeList[i][data.field] == data.value) {
      return [data.treeList[i]];
    }
    if (data.treeList[i].children && data.treeList[i].children.length > 0) {
      // 如果当前节点有子节点，递归查找子节点
      let node: any = getAllParentArr({
        treeList: data.treeList[i].children,
        value: data.value,
        field: data.field,
      });
      if (node.length > 0) {
        return node.concat(data.treeList[i]);
      }
    }
  }
  return [];
};
